package api_policy

import (
	"fmt"
	"restapi/config"
	"restapi/data"
	"restapi/module" //声明的对象在这里
	"strconv"
	"time"
	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
)

// 统一日期格式 (年-月-日 时-分-秒)
const dateLayout = "2006-01-02 15:04:05"

// ///////////////////////////////////////////////创建策略  --over
func Create_Policy(g *gin.Context) {
	logrus.Info("Create_Policy开始处理请求.....")
	//接收变量
	var req module.CreatePolicyRequest
	//反序列化提取json字段数据
	if !decodeJSON(g, &req) {
		return
	}
	//检查必要字段是否为空
	if ok, msg := validateCreatePolicy(&req); !ok {
		respond400(g, msg)
		return
	}

	//业务逻辑-----先判断vsysId是否存在
	if _, err := data.GetVsysByID(req.VsysId); err != nil {
		g.JSON(400, module.CreatePolicyResponse{
			Code:    400,
			Message: "虚拟系统不存在",
		})
		return
	}
	//数量检测
	MAXSIZE := config.C.Limits.PolicyMaxNum
	PolicyList, _, err := data.ListPolicy(2000, 1, req.VsysId, "")
	if err != nil {
		g.JSON(500, module.CreatePolicyResponse{
			Code:    500,
			Message: "查询现有策略时出现错误",
		})
		return
	}
	logrus.Infof("当前已有策略数量: %d", len(PolicyList))
	if len(PolicyList) >= MAXSIZE {
		g.JSON(400, module.CreatePolicyResponse{
			Code:    400,
			Message: fmt.Sprintf("虚拟系统策略数量已达上限%d条", MAXSIZE),
		})
		return
	}
	//检查策略名称长度
	MAXLEN := config.C.Limits.NameMaxLen
	if len(req.Name) > MAXLEN {
		g.JSON(400, module.CreatePolicyResponse{
			Code:    400,
			Message: fmt.Sprintf("策略名称长度不能超过%d字符", MAXLEN),
		})
		return
	}
	//重复性检测
	if ok, msg := validatePolicyConflict(&req); !ok {
		g.JSON(400, module.CreatePolicyResponse{
			Code:    400,
			Message: msg,
		})
		return
	} else {
		//检查通过，可以插入数据
		//没有冲突的条件,可以添加新数据
		newPolicy := data.Policy{
			Name:             req.Name,
			Description:      req.Description,
			Protocol:         req.Protocol,
			ListenInterface:  req.ListenInterface,
			ListenPort:       req.ListenPort,
			ProxyAddress:     req.ProxyAddress,
			ProxyPort:        req.ProxyPort,
			ForwardInterface: req.ForwardInterface,
			ForwardAddress:   req.ForwardAddress,
			ForwardPort:      req.ForwardPort,
			AccessControl:    req.AccessControl,
			VsysId:           req.VsysId,
			CreatedAt:        time.Now(),
			UpdatedAt:        time.Now(),
		}
		//如果添加数据失败
		if err := data.CreatePolicy(&newPolicy); err != nil {
			g.JSON(500, module.CreatePolicyResponse{
				Code:    500,
				Message: fmt.Sprintf("数据库插入失败:%v", err),
			})
			return
		}
	}
	//构建正确响应结果
	g.JSON(200, module.CreatePolicyResponse{
		Code:    200,
		Message: "创建策略成功",
	})
}

// ////////////////////////////////////////////// 删除策略     --- over
func Delete_Policy(g *gin.Context) {
	logrus.Info("Delete_Policy开始处理请求.....")
	var req module.DeletePolicyRequest
	if !decodeJSON(g, &req) {
		return
	}
	logrus.Infof("Delete_Policy 请求IDs=%v", req.Ids)
	//业务逻辑...
	if len(req.Ids) == 0 {
		g.JSON(400, module.DeletePolicyResponse{
			Code:    400,
			Message: "策略数组为空",
		})
		return
	}
	//遍历删除
	for _, id := range req.Ids {
		//先查询策略是否存在
		if p, err := data.GetPolicyByID(id); err == gorm.ErrRecordNotFound || p == nil || err != nil {
			//没有找到
			g.JSON(400, module.DeletePolicyResponse{
				Code:    400,
				Message: fmt.Sprintf("不存在ID为%v的策略信息", id),
			})
			return
		} else {
			//执行删除操作
			if err = data.DeletePolicy(id); err != nil {
				g.JSON(500, module.DeletePolicyResponse{
					Code:    500,
					Message: fmt.Sprintf("删除策略为ID为%v的策略信息失败", id),
				})
			}
		}
	}

	g.JSON(200, module.DeletePolicyResponse{
		Code:    200,
		Message: "删除策略成功",
	})
}

// ////////////////////////////////////////////// 编辑代理策略   --over
// put http://localhost:8080/api/v1/policy?id=123
func Update_Policy(g *gin.Context) {
	logrus.Info("Update_Policy开始处理请求.....")
	var req module.UpdatePolicyRequest
	//提取body
	if !decodeJSON(g, &req) {
		return
	}
	req.Id,_ = strconv.Atoi(g.Query("id"))
	logrus.Infof("Update_Policy URL参数 id=%v", req.Id)
	//检查必要字段是否为空
	if ok, msg := validateUpdatePolicy(&req); !ok {
		respond400(g, msg)
		return
	}
	//业务逻辑...
	//检查该ID是否存在
	p, err := data.GetPolicyByID(req.Id)
	if err == gorm.ErrRecordNotFound || p == nil || err != nil {
		g.JSON(400, module.UpdatePolicyResponse{
			Code:    400,
			Message: fmt.Sprintf("没有ID为%v的策略信息", req.Id),
		})
		return
	}
	//还需要检查名字是否冲突（排除自己）
	logrus.Info("开始检查名字冲突...")
	if req.Name != p.Name {
		//只在要改名时查重
		if result, err := data.IsNameConflict(req.Name); err != nil {
			g.JSON(500, module.UpdatePolicyResponse{
				Code:    500,
				Message: "检查名字冲突时出现错误",
			})
			return
		} else if result {
			g.JSON(400, module.UpdatePolicyResponse{
				Code:    400,
				Message: fmt.Sprintf("策略名称(%s)已存在", req.Name),
			})
			return
		}
	}
	// 检查vsysId是否存在
	if _, err := data.GetVsysByID(req.VsysId); err != nil {
		g.JSON(400, module.UpdatePolicyResponse{
			Code:    400,
			Message: fmt.Sprintf("没有(ID=%d)的虚拟系统", req.VsysId),
		})
		return
	}

	// 检查新vsysId+协议+网口+端口是否冲突（排除自己）
	if result, err := data.IsPolicyConflict(req.Protocol, req.ListenInterface, req.ListenPort, req.VsysId); err != nil {
		g.JSON(500, module.UpdatePolicyResponse{
			Code:    500,
			Message: "检查冲突时出现错误",
		})
		return
	} else if result && (p.Protocol != req.Protocol || p.ListenInterface != req.ListenInterface || p.ListenPort != req.ListenPort || p.VsysId != req.VsysId) {
		//已经存在的目标字段不是自己，那就是冲突
		g.JSON(400, module.UpdatePolicyResponse{
			Code:    400,
			Message: "新策略的协议、接口、端口已存在",
		})
		return
	}

	//没有冲突，直接覆盖
	p.Name = req.Name
	p.Description = req.Description
	p.Protocol = req.Protocol
	p.ListenInterface = req.ListenInterface
	p.ListenPort = req.ListenPort
	p.ProxyAddress = req.ProxyAddress
	p.ProxyPort = req.ProxyPort
	p.ForwardInterface = req.ForwardInterface
	p.ForwardAddress = req.ForwardAddress
	p.ForwardPort = req.ForwardPort
	p.AccessControl = req.AccessControl
	p.VsysId = req.VsysId
	p.UpdatedAt = time.Now()
	if err := data.UpdatePolicy(p); err != nil {
		g.JSON(500, module.UpdatePolicyResponse{
			Code:    500,
			Message: fmt.Sprintf("数据库更新失败:%v", err),
		})
		return
	}

	//构建响应
	g.JSON(200, module.UpdatePolicyResponse{
		Code:    200,
		Message: "编辑策略成功",
	})
}

////////////////////////////////////////////////////查询代理策略

// 查询代理策略列表
// http://localhost:8080/api/v1/policy/list?pageSize=10&pageNum=1&vsysId=1&name=Web  --over
func List_Policy(g *gin.Context) {
	logrus.Info("List_Policy开始处理请求.....")
	var req module.ListPolicyRequest
	// 必填参数存在性检查
	if g.Query("pageSize") == "" {
		respond400(g, "页大小不可为空")
		return
	}
	if g.Query("pageNum") == "" {
		respond400(g, "页码不可为空")
		return
	}
	if g.Query("vsysId") == "" {
		respond400(g, "虚拟系统ID不可为空")
		return
	}
	// 解析查询参数（统一风格）
	parseListPolicyQuery(g, &req)
	// log.Printf("提取到的URL参数:pageSize=%v,pageNum=%v,vsysId=%v,name=%v\n", req.PageSize, req.PageNum, req.VsysId, req.Name)

	// 参数校验
	if ok, msg := validateListPolicy(req.PageSize, req.PageNum, req.VsysId); !ok {
		respond400(g, msg)
		return
	}

	// 业务逻辑...
	list, total, err := data.ListPolicy(req.PageSize, req.PageNum, req.VsysId, req.Name)
	if err != nil {
		g.JSON(500, module.ListPolicyResponse{
			Code:    500,
			Message: fmt.Sprintf("数据库查询失败:%v", err),
		})
		return
	}
	//将查询到的数据转换为响应需要的格式
	newItemList := make([]module.ListPolicyListItem, 0)
	for _, item := range list {
		newItem := module.ListPolicyListItem{
			ID:               item.ID,
			Name:             item.Name,
			Description:      item.Description,
			Protocol:         item.Protocol,
			ListenInterface:  item.ListenInterface,
			ListenPort:       item.ListenPort,
			ProxyAddress:     item.ProxyAddress,
			ProxyPort:        item.ProxyPort,
			ForwardInterface: item.ForwardInterface,
			ForwardAddress:   item.ForwardAddress,
			ForwardPort:      item.ForwardPort,
			AccessControl:    item.AccessControl,
			VsysId:           item.VsysId,
			CreatedAt:        item.CreatedAt.Format(dateLayout),
			UpdatedAt:        item.UpdatedAt.Format(dateLayout),
		}
		newItemList = append(newItemList, newItem)
	}
	//构建响应
	g.JSON(200, module.ListPolicyResponse{
		Code:    200,
		Message: "查询策略列表成功",
		Data: module.ListPolicyData{
			List:        newItemList,
			CurrentPage: req.PageNum,
			Total:       int(total),
		},
	})
}

// 查询单页策略
// 查询单条策略详情
// http://localhost:8080/api/v1/policy/get?id=1001
func Get_Policy(g *gin.Context) {
	logrus.Info("Get_Policy开始处理请求.....")
	idStr := g.Query("id")
	if idStr == "" {
		respond400(g, "策略ID为空")
		return
	}
	idInt, _ := strconv.Atoi(idStr)
	if idInt == 0 {
		respond400(g, "策略ID非法")
		return
	}

	// 业务逻辑...
	Policy, err := data.GetPolicyByID(idInt)
	if err != nil {
		g.JSON(500, module.GetPolicyResponse{
			Code:    500,
			Message: fmt.Sprintf("ID为%v的策略不存在", idInt),
		})
		return
	}
	newPolicyItem := module.ListPolicyListItem{
		ID:               Policy.ID,
		Name:             Policy.Name,
		Description:      Policy.Description,
		Protocol:         Policy.Protocol,
		ListenInterface:  Policy.ListenInterface,
		ListenPort:       Policy.ListenPort,
		ProxyAddress:     Policy.ProxyAddress,
		ProxyPort:        Policy.ProxyPort,
		ForwardInterface: Policy.ForwardInterface,
		ForwardAddress:   Policy.ForwardAddress,
		ForwardPort:      Policy.ForwardPort,
		AccessControl:    Policy.AccessControl,
		VsysId:           Policy.VsysId,
		CreatedAt:        Policy.CreatedAt.Format(dateLayout),
		UpdatedAt:        Policy.UpdatedAt.Format(dateLayout),
	}
	//构建响应
	g.JSON(200, module.GetPolicyResponse{
		Code:    200,
		Message: fmt.Sprintf("查询成功!", idStr),
		Data:    newPolicyItem,
	})
}
